home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrecord-1.8.1 / misc / readcd.c < prev   
Encoding:
C/C++ Source or Header  |  2000-04-24  |  19.3 KB  |  839 lines

  1. /* @(#)readcd.c    1.14 00/04/24 Copyright 1987 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)readcd.c    1.14 00/04/24 Copyright 1987 J. Schilling";
  5. #endif
  6. /*
  7.  *    Skeleton for the use of the scg genearal SCSI - driver
  8.  *
  9.  *    Copyright (c) 1987 J. Schilling
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. #include <mconfig.h>
  28. #include <stdio.h>
  29. #include <standard.h>
  30. #include <unixstd.h>
  31. #include <stdxlib.h>
  32. #include <strdefs.h>
  33. #include <fctldefs.h>
  34. #include <timedefs.h>
  35.  
  36. #include <scg/scgcmd.h>
  37. #include <scg/scsireg.h>
  38. #include <scg/scsitransp.h>
  39.  
  40. #include "cdrecord.h"
  41.  
  42. char    cdr_version[] = "1.8.1";
  43.  
  44. extern    BOOL    getlong        __PR((char *, long *, long, long));
  45. extern    BOOL    getint        __PR((char *, int *, int, int));
  46.  
  47. typedef struct {
  48.     long    start;
  49.     long    end;
  50.     char    *name;
  51. } parm_t;
  52.  
  53. EXPORT    BOOL cvt_cyls        __PR((void));
  54. EXPORT    BOOL cvt_bcyls        __PR((void));
  55. EXPORT    void print_defect_list    __PR((void));
  56. LOCAL    void usage        __PR((int ret));
  57. EXPORT    int main        __PR((int ac, char **av));
  58. LOCAL    int prstats        __PR((void));
  59. LOCAL    void dorw        __PR((SCSI *scgp, char *filename, char* sectors));
  60. LOCAL    void doit        __PR((SCSI *scgp));
  61. #ifdef    used
  62. LOCAL    int read_scsi_g1    __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
  63. #endif
  64.  
  65. EXPORT    int    write_scsi    __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
  66. EXPORT    int    write_g0    __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
  67. EXPORT    int    write_g1    __PR((SCSI *scgp, caddr_t bp, long addr, int cnt));
  68.  
  69. #ifdef    used
  70. LOCAL    void    Xrequest_sense    __PR((SCSI *scgp));
  71. #endif
  72. LOCAL    int    rrr        __PR((SCSI *scgp, caddr_t bp, long addr, long cnt));
  73. LOCAL    void    read_disk    __PR((SCSI    *scgp, parm_t *parmp));
  74. LOCAL    void    write_disk    __PR((SCSI *scgp, parm_t *parmp));
  75. LOCAL    int    choice        __PR((int n));
  76. LOCAL    void    ra        __PR((SCSI *scgp));
  77.  
  78. #ifndef    TRUE
  79. #    define    TRUE    1
  80. #    define    FALSE    0
  81. #endif
  82.  
  83. struct timeval    starttime;
  84. struct timeval    stoptime;
  85.  
  86. char    *Sbuf;
  87. long    Sbufsize;
  88.  
  89. int    help;
  90. BOOL    is_suid;
  91. BOOL    is_cdrom;
  92. BOOL    do_write;
  93.  
  94. struct    scsi_format_data fmt;
  95.  
  96. /*XXX*/EXPORT    BOOL cvt_cyls(){ return (FALSE);}
  97. /*XXX*/EXPORT    BOOL cvt_bcyls(){ return (FALSE);}
  98. /*XXX*/EXPORT    void print_defect_list(){}
  99.  
  100. LOCAL void
  101. usage(ret)
  102.     int    ret;
  103. {
  104.     error("Usage:\treadcd [options]\n");
  105.     error("options:\n");
  106.     error("\t-version    print version information and exit\n");
  107.     error("\tdev=target    SCSI target to use\n");
  108.     error("\tf=filename    Name of file to read/write\n");
  109.     error("\tsectors=range    Range of sectors to read/write\n");
  110.     error("\t-w        Switch to write mode\n");
  111.     error("\tkdebug=#,kd=#\tdo Kernel debugging\n");
  112.     error("\t-v        increment general verbose level by one\n");
  113.     error("\t-V        increment SCSI command transport verbose level by one\n");
  114.     error("\t-silent,-s\tdo not print status of erreneous commands\n");
  115.     exit(ret);
  116. }    
  117.  
  118. char    opts[]   = "kdebug#,kd#,verbose+,v+,Verbose,V+,silent,s,debug,help,h,version,dev*,f*,sectors*,w";
  119.  
  120. EXPORT int
  121. main(ac, av)
  122.     int    ac;
  123.     char    *av[];
  124. {
  125.     char    *dev = NULL;
  126.     int    fcount;
  127.     int    cac;
  128.     char    * const *cav;
  129.     int    scsibus    = 0;
  130.     int    target    = 0;
  131.     int    lun    = 0;
  132.     int    silent    = 0;
  133.     int    verbose    = 0;
  134.     int    lverbose= 0;
  135.     int    kdebug    = 0;
  136.     int    debug    = 0;
  137.     int    pversion = 0;
  138.     SCSI    *scgp;
  139.     char    *filename= NULL;
  140.     char    *sectors = NULL;
  141.  
  142.     save_args(ac, av);
  143.  
  144.     cac = --ac;
  145.     cav = ++av;
  146.  
  147.     if(getallargs(&cac, &cav, opts,
  148.             &kdebug, &kdebug,
  149.             &verbose, &verbose,
  150.             &lverbose, &lverbose,
  151.             &silent, &silent, &debug,
  152.             &help, &help, &pversion,
  153.             &dev, &filename, §ors, &do_write) < 0) {
  154.         errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
  155.         usage(EX_BAD);
  156.     }
  157.     if (help)
  158.         usage(0);
  159.     if (pversion) {
  160.         printf("readcd %s (%s-%s-%s) Copyright (C) 1987, 1995-2000 J÷rg Schilling\n",
  161.                                 cdr_version,
  162.                                 HOST_CPU, HOST_VENDOR, HOST_OS);
  163.         exit(0);
  164.     }
  165.  
  166.     fcount = 0;
  167.     cac = ac;
  168.     cav = av;
  169.  
  170.     while(getfiles(&cac, &cav, opts) > 0) {
  171.         fcount++;
  172.         if (fcount == 1) {
  173.             if (*astoi(cav[0], &target) != '\0') {
  174.                 errmsgno(EX_BAD,
  175.                     "Target '%s' is not a Number.\n",
  176.                                 cav[0]);
  177.                 usage(EX_BAD);
  178.                 /* NOTREACHED */
  179.             }
  180.         }
  181.         if (fcount == 2) {
  182.             if (*astoi(cav[0], &lun) != '\0') {
  183.                 errmsgno(EX_BAD,
  184.                     "Lun is '%s' not a Number.\n",
  185.                                 cav[0]);
  186.                 usage(EX_BAD);
  187.                 /* NOTREACHED */
  188.             }
  189.         }
  190.         if (fcount == 3) {
  191.             if (*astoi(cav[0], &scsibus) != '\0') {
  192.                 errmsgno(EX_BAD,
  193.                     "Scsibus is '%s' not a Number.\n",
  194.                                 cav[0]);
  195.                 usage(EX_BAD);
  196.                 /* NOTREACHED */
  197.             }
  198.         } else {
  199.             scsibus = 0;
  200.         }
  201.         cac--;
  202.         cav++;
  203.     }
  204. /*error("dev: '%s'\n", dev);*/
  205.  
  206.     if (dev) {
  207.         char    errstr[80];
  208.  
  209.         if ((scgp = open_scsi(dev, errstr, sizeof(errstr), debug, lverbose)) == (SCSI *)0)
  210.             comerr("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
  211. /*        scsi_settimeout(scgp, timeout);*/
  212.     } else {
  213.         if (scsibus == -1 && target >= 0 && lun >= 0)
  214.             scsibus = 0;
  215.  
  216.         scgp = scsi_smalloc();
  217.         scgp->debug = debug;
  218.         scgp->kdebug = kdebug;
  219.         scgp->scsibus = scsibus;
  220.         scgp->target = target;
  221.         scgp->lun = lun;
  222.  
  223.         if (!scsi_open(scgp, NULL, scsibus, target, lun))
  224.             comerr("Cannot open SCSI driver.\n");
  225.  
  226.         scgp->scsibus = scsibus;
  227.         scgp->target = target;
  228.         scgp->lun = lun;
  229.     }
  230.     scgp->silent = silent;
  231.     scgp->verbose = verbose;
  232.     scgp->debug = debug;
  233.     scgp->kdebug = kdebug;
  234.  
  235.     Sbufsize = scsi_bufsize(scgp, 256*1024L);
  236.     if ((Sbuf = scsi_getbuf(scgp, Sbufsize)) == NULL)
  237.         comerr("Cannot get SCSI I/O buffer.\n");
  238.  
  239.     is_suid = geteuid() != getuid();
  240.     /*
  241.      * We don't need root privilleges anymore.
  242.      */
  243. #ifdef    HAVE_SETREUID
  244.     if (setreuid(-1, getuid()) < 0)
  245. #else
  246. #ifdef    HAVE_SETEUID
  247.     if (seteuid(getuid()) < 0)
  248. #else
  249.     if (setuid(getuid()) < 0)
  250. #endif
  251. #endif
  252.         comerr("Panic cannot set back efective uid.\n");
  253.  
  254.     /* code to use SCG */
  255.  
  256.     do_inquiry(scgp, FALSE);
  257.     if (is_suid) {
  258.         if (scgp->inq->type != INQ_ROMD)
  259.             comerrno(EX_BAD, "Not root. Will only work on CD-ROM in suid mode\n");
  260.     }
  261.  
  262.     if (filename || sectors) {
  263.         dorw(scgp, filename, sectors);
  264.     } else {
  265.         doit(scgp);
  266.     }
  267.     return (0);
  268. }
  269.  
  270. LOCAL int
  271. prstats()
  272. {
  273.     int    sec;
  274.     int    usec;
  275.     int    tmsec;
  276.  
  277.     if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
  278.         comerr("Cannot get time\n");
  279.  
  280.     sec = stoptime.tv_sec - starttime.tv_sec;
  281.     usec = stoptime.tv_usec - starttime.tv_usec;
  282.     tmsec = sec*1000 + usec/1000;
  283. #ifdef    lint
  284.     tmsec = tmsec;    /* Bisz spaeter */
  285. #endif
  286.     if (usec < 0) {
  287.         sec--;
  288.         usec += 1000000;
  289.     }
  290.  
  291.     error("Time total: %d.%03dsec\n", sec, usec/1000);
  292. /*    return (sec + (usec / 500000));*/
  293.     return (1000*sec + (usec / 1000));
  294. }
  295.  
  296. LOCAL void
  297. dorw(scgp, filename, sectors)
  298.     SCSI    *scgp;
  299.     char    *filename;
  300.     char    *sectors;
  301. {
  302.     parm_t    params;
  303.     char    *p = NULL;
  304.  
  305.     params.start = 0;
  306.     params.end = -1;
  307.     params.name = NULL;
  308.  
  309.     if (filename)
  310.         params.name = filename;
  311.     if (sectors)
  312.         p = astol(sectors, ¶ms.start);
  313.     if (p && *p == '-')
  314.         p = astol(++p, ¶ms.end);
  315.     if (p && *p != '\0')
  316.         comerrno(EX_BAD, "Not a valid sector range '%s'\n", sectors);
  317.  
  318.     if (!wait_unit_ready(scgp, 60))
  319.         comerr("Device not ready.\n");
  320.  
  321.     if (do_write)
  322.         write_disk(scgp, ¶ms);
  323.     else
  324.         read_disk(scgp, ¶ms);
  325. }
  326.  
  327. LOCAL void
  328. doit(scgp)
  329.     SCSI    *scgp;
  330. {
  331.     int    i = 0;
  332.  
  333.     for(;;) {
  334.         if (!wait_unit_ready(scgp, 60))
  335.             comerr("Device not ready.\n");
  336.  
  337.         printf("0:read 1:veri   2:erase   3:read buffer 4:cache 5:ovtime 6:cap\n");
  338.         printf("7:wne  8:floppy 9:verify 10:checkcmds  11:read disk 12:write disk\n");
  339.         printf("13:scsireset 14:seektest 15: readda\n");
  340.  
  341.         getint("Enter selection:", &i, 0, 15);
  342.         switch (i) {
  343.  
  344.         case 11:    read_disk(scgp, 0);    break;
  345.         case 12:    write_disk(scgp, 0);    break;
  346.         case 15:    ra(scgp);        break;
  347.         }
  348.     }
  349. }
  350.  
  351. #ifdef    used
  352. LOCAL int
  353. read_scsi_g1(scgp, bp, addr, cnt)
  354.     SCSI    *scgp;
  355.     caddr_t    bp;
  356.     long    addr;
  357.     int    cnt;
  358. {
  359.     register struct    scg_cmd    *scmd = scgp->scmd;
  360.  
  361.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  362.     scmd->addr = bp;
  363. /*    scmd->size = cnt*512;*/
  364.     scmd->size = cnt*scgp->cap->c_bsize;
  365.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  366.     scmd->cdb_len = SC_G1_CDBLEN;
  367.     scmd->sense_len = CCS_SENSE_LEN;
  368.     scmd->target = scgp->target;
  369.     scmd->cdb.g1_cdb.cmd = 0x28;
  370.     scmd->cdb.g1_cdb.lun = scgp->lun;
  371.     g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  372.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  373.     
  374.     scgp->cmdname = "read extended";
  375.  
  376.     return (scsicmd(scgp));
  377. }
  378. #endif
  379.  
  380. #define    G0_MAXADDR    0x1FFFFFL
  381.  
  382. EXPORT int
  383. write_scsi(scgp, bp, addr, cnt)
  384.     SCSI    *scgp;
  385.     caddr_t    bp;
  386.     long    addr;
  387.     int    cnt;
  388. {
  389.     if(addr <= G0_MAXADDR)
  390.         return(write_g0(scgp, bp, addr, cnt));
  391.     else
  392.         return(write_g1(scgp, bp, addr, cnt));
  393. }
  394.  
  395. EXPORT int
  396. write_g0(scgp, bp, addr, cnt)
  397.     SCSI    *scgp;
  398.     caddr_t    bp;
  399.     long    addr;
  400.     int    cnt;
  401. {
  402.     register struct    scg_cmd    *scmd = scgp->scmd;
  403.  
  404.     if (scgp->cap->c_bsize <= 0)
  405.         raisecond("capacity_not_set", 0L);
  406.  
  407.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  408.     scmd->addr = bp;
  409.     scmd->size = cnt*scgp->cap->c_bsize;
  410.     scmd->flags = SCG_DISRE_ENA;
  411.     scmd->cdb_len = SC_G0_CDBLEN;
  412.     scmd->sense_len = CCS_SENSE_LEN;
  413.     scmd->target = scgp->target;
  414.     scmd->cdb.g0_cdb.cmd = SC_WRITE;
  415.     scmd->cdb.g0_cdb.lun = scgp->lun;
  416.     g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
  417.     scmd->cdb.g0_cdb.count = cnt;
  418.     
  419.     scgp->cmdname = "write_g0";
  420.  
  421.     return (scsicmd(scgp));
  422. }
  423.  
  424. EXPORT int
  425. write_g1(scgp, bp, addr, cnt)
  426.     SCSI    *scgp;
  427.     caddr_t    bp;
  428.     long    addr;
  429.     int    cnt;
  430. {
  431.     register struct    scg_cmd    *scmd = scgp->scmd;
  432.  
  433.     if (scgp->cap->c_bsize <= 0)
  434.         raisecond("capacity_not_set", 0L);
  435.  
  436.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  437.     scmd->addr = bp;
  438.     scmd->size = cnt*scgp->cap->c_bsize;
  439.     scmd->flags = SCG_DISRE_ENA;
  440.     scmd->cdb_len = SC_G1_CDBLEN;
  441.     scmd->sense_len = CCS_SENSE_LEN;
  442.     scmd->target = scgp->target;
  443.     scmd->cdb.g1_cdb.cmd = SC_EWRITE;
  444.     scmd->cdb.g1_cdb.lun = scgp->lun;
  445.     g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  446.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  447.     
  448.     scgp->cmdname = "write_g1";
  449.  
  450.     return (scsicmd(scgp));
  451. }
  452.  
  453. #ifdef    used
  454. LOCAL void
  455. Xrequest_sense(scgp)
  456.     SCSI    *scgp;
  457. {
  458.     char    sense_buf[32];
  459.     struct    scg_cmd ocmd;
  460.     int    sense_count;
  461.     char    *cmdsave;
  462.     register struct    scg_cmd    *scmd = scgp->scmd;
  463.  
  464.     cmdsave = scgp->cmdname;
  465.  
  466.     movebytes(scmd, &ocmd, sizeof(*scmd));
  467.  
  468.     fillbytes((caddr_t)sense_buf, sizeof(sense_buf), '\0');
  469.  
  470.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  471.     scmd->addr = (caddr_t)sense_buf;
  472.     scmd->size = sizeof(sense_buf);
  473.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  474.     scmd->cdb_len = SC_G0_CDBLEN;
  475.     scmd->sense_len = CCS_SENSE_LEN;
  476.     scmd->target = scgp->target;
  477.     scmd->cdb.g1_cdb.cmd = 0x3;
  478.     scmd->cdb.g1_cdb.lun = scgp->lun;
  479.     scmd->cdb.g0_cdb.count = sizeof(sense_buf);
  480.     
  481.     scgp->cmdname = "request sense";
  482.  
  483.     scsicmd(scgp);
  484.  
  485.     sense_count = sizeof(sense_buf) - scsigetresid(scgp);
  486.     movebytes(&ocmd, scmd, sizeof(*scmd));
  487.     scmd->sense_count = sense_count;
  488.     movebytes(sense_buf, (u_char *)&scmd->sense, scmd->sense_count);
  489.  
  490.     scgp->cmdname = cmdsave;
  491.     scsiprinterr(scgp);
  492.     scsiprintresult(scgp);    /* XXX restore key/code in future */
  493. }
  494. #endif
  495.  
  496. /*#define    MAX_RETRY    32*/
  497. #define    MAX_RETRY    128
  498.  
  499. LOCAL int
  500. rrr(scgp, bp, addr, cnt)
  501.     SCSI    *scgp;
  502.     caddr_t    bp;
  503.     long    addr;
  504.     long    cnt;
  505. {
  506.     int    secsize = scgp->cap->c_bsize;
  507.     int    try = 0;
  508.     int    err;
  509.     char    dummybuf[4000];
  510.  
  511.     errmsgno(EX_BAD, "Retrying from sector %d.\n", addr);
  512.     while (cnt > 0) {
  513.         error(".");
  514.  
  515.         do {
  516.             if (try != 0) {
  517.                 if ((try % 8) == 0) {
  518.                     error("+");
  519.                     scgp->silent++;
  520.                     read_g1(scgp, dummybuf, scgp->cap->c_baddr, 1);
  521.                     scgp->silent--;
  522.                 } else if ((try % 4) == 0) {
  523.                     error("-");
  524.                     scgp->silent++;
  525.                     read_g1(scgp, dummybuf, 0, 1);
  526.                     scgp->silent--;
  527.                 } else {
  528.                     error("~");
  529.                     scgp->silent++;
  530.                     read_g1(scgp, dummybuf, choice(scgp->cap->c_baddr), 1);
  531.                     scgp->silent--;
  532.                 }
  533.             }
  534.  
  535.             scgp->silent++;
  536.             err = read_g1(scgp, bp, addr, 1);
  537.             scgp->silent--;
  538.  
  539.             if (err < 0) {
  540.                 err = scgp->scmd->ux_errno;
  541. /*                error("\n");*/
  542. /*                errmsgno(err, "Cannot read source disk\n");*/
  543.             } else {
  544.                 break;
  545.             }
  546.         } while (++try < MAX_RETRY);
  547.  
  548.         if (try >= MAX_RETRY) {
  549.             error("\n");
  550.             errmsgno(err, "Error not corrected.\n");
  551.             return (-1);
  552.         } else {
  553.             if (try > 1) {
  554.                 error("\n");
  555.                 errmsgno(EX_BAD, "Error corrected after %d tries.\n", try);
  556.             }
  557.         }
  558.         try = 0;
  559.         cnt -= 1;
  560.         addr += 1;
  561.         bp += secsize;
  562.     }
  563.     return (0);
  564. }
  565.  
  566. LOCAL void
  567. read_disk(scgp, parmp)
  568.     SCSI    *scgp;
  569.     parm_t    *parmp;
  570. {
  571.     char    filename[512];
  572.     char    *defname = "disk.out";
  573.     FILE    *f;
  574.     long    addr;
  575.     long    cnt;
  576.     long    end;
  577.     int    nsec;
  578.     long    start = 0L;
  579.     int    err = 0;
  580.  
  581.     if (is_suid) {
  582.         if (scgp->inq->type != INQ_ROMD)
  583.             comerrno(EX_BAD, "Not root. Will only read from CD in suid mode\n");
  584.     }
  585.  
  586.     filename[0] ='\0';
  587.     read_capacity(scgp);
  588.     end = scgp->cap->c_baddr + 1;
  589.  
  590.     if (end <= 0)
  591.         end = 10000000;    /* Hack to read empty (e.g. blank=fast) disks */
  592.  
  593.     if (parmp) {
  594.         if (parmp->name)
  595.             defname = parmp->name;
  596.         error("Copy from SCSI (%d,%d,%d) disk to file '%s'\n",
  597.                     scgp->scsibus, scgp->target, scgp->lun,
  598.                     defname);
  599.  
  600.         addr = start = parmp->start;
  601.         if (parmp->end != -1 && parmp->end < end)
  602.             end = parmp->end;
  603.         cnt = Sbufsize / scgp->cap->c_bsize;
  604.     }
  605. else {
  606.  
  607.     error("Copy from SCSI (%d,%d,%d) disk to file\n",
  608.                     scgp->scsibus, scgp->target, scgp->lun);
  609.     error("Enter filename [%s]: ", defname);flush();
  610.     (void)getline(filename, sizeof(filename));
  611.  
  612.     addr = start;
  613.     getlong("Enter starting sector for copy:", &addr, start, end-1);
  614.     start = addr;
  615.     cnt = end - addr;
  616.     getlong("Enter number of sectors to copy:", &cnt, 1L, cnt);
  617.     end = addr + cnt;
  618.  
  619.     cnt = Sbufsize / scgp->cap->c_bsize;
  620.     getlong("Enter number of sectors per copy:", &cnt, 1L, cnt);
  621. /*    error("end:  %8ld\n", end);*/
  622. }
  623.  
  624.     if (filename[0] == '\0')
  625.         strcpy(filename, defname);
  626.     if (streql(filename, "-")) {
  627.         f = stdout;
  628. #if    defined(__CYGWIN32__) || defined(__EMX__)
  629.         setmode(STDOUT_FILENO, O_BINARY);
  630. #endif
  631.     } else if ((f = fileopen(filename, "wcub")) == NULL)
  632.         comerr("Cannot open '%s'.\n", filename);
  633.  
  634.     error("end:  %8ld\n", end);
  635.     if (gettimeofday(&starttime, (struct timezone *)0) < 0)
  636.         comerr("Cannot get start time\n");
  637.  
  638.     for(;addr < end; addr += cnt) {
  639.  
  640.         if ((addr + cnt) > end)
  641.             cnt = end - addr;
  642.  
  643.         error("addr: %8d cnt: %d\r", addr, cnt);
  644.  
  645. /*        if (read_scsi(scgp, Sbuf, addr, cnt) < 0) {*/
  646.         if (read_g1(scgp, Sbuf, addr, cnt) < 0) {
  647.             err = scgp->scmd->ux_errno;
  648.             error("\n");
  649.             errmsgno(err, "Cannot read source disk\n");
  650.             if (rrr(scgp, Sbuf, addr, cnt) < 0)
  651.                 goto out;
  652.         }
  653.         if (filewrite(f, Sbuf, cnt * scgp->cap->c_bsize) < 0) {
  654.             err = geterrno();
  655.             error("\n");
  656.             errmsgno(err, "Cannot write '%s'\n", filename);
  657.             break;
  658.         }
  659.     }
  660.     error("addr: %8d", addr);
  661. out:
  662.     error("\n");
  663.     nsec = prstats();
  664. /*    error("%d\n",nsec);*/
  665.     error("Read %.2f kB at %.1f kB/sec.\n",
  666.         (addr - start)/(1024.0/scgp->cap->c_bsize),
  667.         ((addr - start)/(1024.0/scgp->cap->c_bsize)) / (0.001*nsec));
  668.     if (err)
  669.         exit(err);
  670. }
  671.  
  672. LOCAL void
  673. write_disk(scgp, parmp)
  674.     SCSI    *scgp;
  675.     parm_t    *parmp;
  676. {
  677.     char    filename[512];
  678.     char    *defname = "disk.out";
  679.     FILE    *f;
  680.     long    addr = 0L;
  681.     long    cnt;
  682.     long    amt;
  683.     long    end;
  684.     int    nsec;
  685.     int    start;
  686.  
  687.     if (is_suid)
  688.         comerrno(EX_BAD, "Not root. Will not write in suid mode\n");
  689.  
  690.     read_capacity(scgp);
  691.     end = scgp->cap->c_baddr + 1;
  692.  
  693.     if (end <= 0)
  694.         end = 10000000;    /* Hack to write empty disks */
  695.  
  696.     if (parmp) {
  697.         if (parmp->name)
  698.             defname = parmp->name;
  699.         error("Copy from file '%s' tp SCSI (%d,%d,%d) disk\n",
  700.                     defname,
  701.                     scgp->scsibus, scgp->target, scgp->lun);
  702.  
  703.         addr = start = parmp->start;
  704.         if (parmp->end != -1 && parmp->end < end)
  705.             end = parmp->end;
  706.         cnt = Sbufsize / scgp->cap->c_bsize;
  707.     }
  708. else {
  709.  
  710.     error("Copy from file to SCSI (%d,%d,%d) disk\n",
  711.                     scgp->scsibus, scgp->target, scgp->lun);
  712.     error("Enter filename [%s]: ", defname);flush();
  713.     (void)getline(filename, sizeof(filename));
  714.     error("Notice: reading from file always starts at file offset 0.\n");
  715.  
  716.     getlong("Enter starting sector for copy:", &addr, 0L, end-1);
  717.     start = addr;
  718.     cnt = end - addr;
  719.     getlong("Enter number of sectors to copy:", &end, 1L, end);
  720.     end = addr + cnt;
  721.  
  722.     cnt = Sbufsize / scgp->cap->c_bsize;
  723.     getlong("Enter number of sectors per copy:", &cnt, 1L, cnt);
  724. /*    error("end:  %8ld\n", end);*/
  725. }
  726.  
  727.     if (filename[0] == '\0')
  728.         strcpy(filename, defname);
  729.     if (streql(filename, "-")) {
  730.         f = stdin;
  731. #if    defined(__CYGWIN32__) || defined(__EMX__)
  732.         setmode(STDIN_FILENO, O_BINARY);
  733. #endif
  734.     } else if ((f = fileopen(filename, "rub")) == NULL)
  735.         comerr("Cannot open '%s'.\n", filename);
  736.  
  737.     error("end:  %8ld\n", end);
  738.     if (gettimeofday(&starttime, (struct timezone *)0) < 0)
  739.         comerr("Cannot get start time\n");
  740.  
  741.     for(;addr < end; addr += cnt) {
  742.  
  743.         if ((addr + cnt) > end)
  744.             cnt = end - addr;
  745.  
  746.         error("addr: %8d cnt: %d\r", addr, cnt);
  747.  
  748.         if ((amt = fileread(f, Sbuf, cnt * scgp->cap->c_bsize)) < 0)
  749.             comerr("Cannot read '%s'\n", filename);
  750.         if (amt == 0)
  751.             break;
  752.         if ((amt / scgp->cap->c_bsize) < cnt)
  753.             cnt = amt / scgp->cap->c_bsize;
  754.         if (write_scsi(scgp, Sbuf, addr, cnt) < 0)
  755.             comerrno(scgp->scmd->ux_errno,
  756.                     "Cannot write destination disk\n");
  757.     }
  758.     error("addr: %8d\n", addr);
  759.     nsec = prstats();
  760.     error("Wrote %.2f kB at %.1f kB/sec.\n",
  761.         (double)(addr - start)/(1024.0/scgp->cap->c_bsize),
  762.         (double)((addr - start)/(1024.0/scgp->cap->c_bsize)) / nsec);
  763. }
  764.  
  765. LOCAL int
  766. choice(n)
  767.     int    n;
  768. {
  769. #if    defined(HAVE_DRAND48)
  770.     extern    double    drand48 __PR((void));
  771.  
  772.     return drand48() * n;
  773. #else
  774. #    if    defined(HAVE_RAND)
  775.     extern    int    rand __PR((void));
  776.  
  777.     return rand() % n;
  778. #    else
  779.     return (0);
  780. #    endif
  781. #endif
  782. }
  783.  
  784. LOCAL void
  785. ra(scgp)
  786.     SCSI    *scgp;
  787. {
  788. /*    char    filename[512];*/
  789.     FILE    *f;
  790. /*    long    addr = 0L;*/
  791. /*    long    cnt;*/
  792. /*    long    end;*/
  793. /*    int    nsec;*/
  794. /*    int    start;*/
  795. /*    int    err = 0;*/
  796.  
  797.     select_secsize(scgp, 2352);
  798.     read_capacity(scgp);
  799.     fillbytes(Sbuf, 50*2352, 0);
  800.     if (read_g1(scgp, Sbuf, 0, 50) < 0)
  801.         errmsg("read CD\n");
  802.     f = fileopen("DDA", "wctb");
  803. /*    filewrite(f, Sbuf, 50 * 2352 - scsigetresid(scgp));*/
  804.     filewrite(f, Sbuf, 50 * 2352 );
  805.     fclose(f);
  806. }
  807.  
  808. #ifdef    XXX
  809. EXPORT int
  810. read_da(scgp, bp, addr, cnt)
  811.     SCSI    *scgp;
  812.     caddr_t    bp;
  813.     long    addr;
  814.     int    cnt;
  815. {
  816.     register struct    scg_cmd    *scmd = scgp->scmd;
  817.  
  818.     if (scgp->cap->c_bsize <= 0)
  819.         raisecond("capacity_not_set", 0L);
  820.  
  821.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  822.     scmd->addr = bp;
  823.     scmd->size = cnt*scgp->cap->c_bsize;
  824.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  825.     scmd->cdb_len = SC_G5_CDBLEN;
  826.     scmd->sense_len = CCS_SENSE_LEN;
  827.     scmd->target = scgp->target;
  828. /*    scmd->cdb.g5_cdb.cmd = SC_EREAD;*/
  829.     scmd->cdb.g5_cdb.cmd = 0xd9;
  830.     scmd->cdb.g5_cdb.lun = scgp->lun;
  831.     g5_cdbaddr(&scmd->cdb.g1_cdb, addr);
  832.     g5_cdblen(&scmd->cdb.g1_cdb, cnt);/* XXX subscript out of range ?? */
  833.     
  834.     scgp->cmdname = "read_g1";
  835.  
  836.     return (scsicmd(scgp));
  837. }
  838. #endif
  839.